package com.itxh.mvc.mapping;

import com.itxh.annotation.Controller;
import com.itxh.annotation.RequestMapping;
import com.itxh.aware.BeanFactoryAware;
import com.itxh.factory.BeanFactory;
import com.itxh.factory.DefaultListableBeanFactory;
import com.itxh.init.InitializingBean;
import com.itxh.model.BeanDefinition;
import com.itxh.mvc.handler.HandlerMethod;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class RequestMappingHandlerMapping implements HandlerMapping, BeanFactoryAware, InitializingBean {
    private Map<String, HandlerMethod> handlerMappings = new HashMap<>();

    private DefaultListableBeanFactory beanFactory;

    // 如何对handlerMappings进行初始化
    @Override
    public void afterPropertiesSet() {
        List<BeanDefinition> beanDefinitions = beanFactory.getBeanDefinitions();
        for (BeanDefinition bd : beanDefinitions) {
            Class clazzType = bd.getClazzType();
            if(isHandler(clazzType)){
                RequestMapping RequestMapping1 = (RequestMapping) clazzType.getAnnotation(RequestMapping.class);
                String classUrl = RequestMapping1.value();
                Method[] methods = clazzType.getDeclaredMethods();
                for (Method method : methods) {
                    if(method.isAnnotationPresent(RequestMapping.class)){
                        RequestMapping requestMapping2 = method.getAnnotation(RequestMapping.class);
                        String methodUrl = requestMapping2.value();

                        StringBuffer sb = new StringBuffer();
                        if (classUrl != null){
                            if (classUrl.startsWith("/")){
                                sb.append(classUrl);
                            }else{
                                sb.append("/").append(classUrl);
                            }
                        }
                        if (methodUrl != null){
                            if (methodUrl.startsWith("/")){
                                sb.append(methodUrl);
                            }else{
                                sb.append("/").append(methodUrl);
                            }
                        }

                        HandlerMethod hm = new HandlerMethod(beanFactory.getBean(bd.getId()),method);
                        handlerMappings.put(sb.toString(),hm);
                    }
                }
            }
        }
    }

    private boolean isHandler(Class clazzType) {
        return clazzType.isAnnotationPresent(Controller.class) || clazzType.isAnnotationPresent(RequestMapping.class);
    }

    @Override
    public Object getHandler(HttpServletRequest request) {
        String uri = request.getRequestURI();
        if (uri == null || "".equals(uri)){
            return  null;
        }

        return handlerMappings.get(uri);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = (DefaultListableBeanFactory) beanFactory;
    }


}
